﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using iRealtor.Maps.Core.Entities;
using iRealtor.Maps.Core.Helpers;
using iRealtor.Maps.Core.Services;
using iRealtor.Maps.DataAccess.Models;
using iRealtor.Maps.WebUI.Models;

namespace iRealtor.Maps.WebUI.Controllers
{
	public class MapController : Controller
	{
		private readonly PlacesService _placeService;

		public MapController()
		{
			_placeService = new PlacesService();
			new GroupsService();
		}

		public ActionResult Index(int scale = 1)
		{
			var viewModel = new MapViewModel();
			return View(viewModel);
		}

		[HttpGet]
		public JsonResult GetPlacesByScale(int? zoom)
		{
			List<PlaceView> places = _placeService.GetPlaces();

			var groupViews = GetGroupViews(zoom, places);
			var tempGroupViews = new List<GroupView>(groupViews);

			var rand = new Random(DateTime.Now.Millisecond);
			while (tempGroupViews.Any())
			{
				var index = rand.Next(tempGroupViews.Count);
				var randGroup = groupViews.FirstOrDefault(g => g.Group.GroupId == tempGroupViews[index].Group.GroupId);
				if (randGroup != null)
					randGroup.IsBig = true;
				else
					break;

				var groups =
					tempGroupViews.Where(
						g =>
						zoom != null && DistanceHelper.PixelDistance(g.Group.Latitude,
																	g.Group.Longitude, 
																	randGroup.Group.Latitude,
																	randGroup.Group.Longitude, 
																	zoom.Value) < 50).ToList();
				tempGroupViews.Remove(randGroup);
				foreach (var groupView in groups)
				{
					tempGroupViews.Remove(groupView);
				}
			}

			return Json(groupViews, JsonRequestBehavior.AllowGet);
		}

		#region Helpers

		private static List<GroupView> GetGroupViews(int? zoom, List<PlaceView> places)
		{
			var groupViews = new List<GroupView>();
			int groupId = 1;
			
			while (places.Any())
			{
				var placeView = places[0];

				var gv = new GroupView()
							{
								Group = null,
								PlaceViews = new List<PlaceView>()
							};

				const int distance = 10;
				List<PlaceView> groupPlacesViews =
					places.Where(
						tp =>
						zoom != null && DistanceHelper.PixelDistance(tp.Place.Latitude,
																	 tp.Place.Longitude,
																	 placeView.Place.Latitude,
																	 placeView.Place.Longitude,
																	 zoom.Value) < distance).ToList();

				gv.PlaceViews = groupPlacesViews;

				MapPoint mp = GetCenter(new List<Place>(groupPlacesViews.Select(pv => pv.Place)));

				gv.Group = new Group()
							{
								GroupId = groupId,
								Latitude = mp.Latitude,
								Longitude = mp.Longitude
							};

				groupViews.Add(gv);
				groupId++;

				places.Remove(placeView);
				foreach (var groupPlacesView in groupPlacesViews)
				{
					places.Remove(groupPlacesView);
				}
			}
			return groupViews;
		}

		private static MapPoint GetCenter(List<Place> places)
		{
			var point = new MapPoint
			{
				Latitude = places.Average(p => p.Latitude),
				Longitude = places.Average(p => p.Longitude)
			};

			return point;
		}

		#endregion
	}
}
